; Published under the MIT License

; Copyright(c) 2010 Ajtaji and Zenner

; Permission is hereby granted, free of charge, To any person obtaining a copy
; of this software And associated documentation files(the "Software"), To deal
; in the Software without restriction, including without limitation the rights
; To use, copy, modify, merge, publish, distribute, sublicense, And/Or sell
; copies of the Software, And To permit persons To whom the Software is
; furnished To do so, subject To the following conditions :

; The above copyright notice And this permission notice shall be included in
; all copies Or substantial portions of the Software.

; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS Or
; IMPLIED, INCLUDING BUT Not LIMITED To THE WARRANTIES OF MERCHANTABILITY,
; FITNESS For A PARTICULAR PURPOSE And NONINFRINGEMENT.IN NO EVENT SHALL THE
; AUTHORS Or COPYRIGHT HOLDERS BE LIABLE For ANY CLAIM, DAMAGES Or OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT Or OTHERWISE, ARISING FROM,
; OUT OF Or IN CONNECTION With THE SOFTWARE Or THE USE Or OTHER DEALINGS IN
; THE SOFTWARE.



; Fast Image Routine
;wingdi.h constants
#ANTIALIASED_QUALITY=4 ;for CreateFont_()
#DM_BITSPERPEL=$40000
#DM_PELSWIDTH=$80000
#DM_PELSHEIGHT=$100000
;- Procedure

; QueryPerformanceFrequency_(@PerformanceFrequency)
; performancefrequency=performancefrequency/10000
Procedure.f mod_f(f1.d, f2.d)
  Protected Retval.d
  While (retval+f2) <= f1
    retval + f2
  Wend
  ProcedureReturn (f1 - retval)
EndProcedure
; Procedure GetTimer()
;   
;   QueryPerformanceCounter_(@timerresult)
;   tresult.q=(timerresult/performancefrequency)
;   ProcedureReturn tresult
;   
; EndProcedure
Procedure CopyImageToMemory(ImageNo, Memory)
  
  
  Protected TemporaryDC.l, TemporaryBitmap.BITMAP, TemporaryBitmapInfo.BITMAPINFO
  
  TemporaryDC = CreateDC_("DISPLAY", #Null, #Null, #Null)
  
  GetObject_(ImageID(ImageNo), SizeOf(BITMAP), TemporaryBitmap.BITMAP)
  
  TemporaryBitmapInfo\bmiHeader\biSize        = SizeOf(BITMAPINFOHEADER)
  TemporaryBitmapInfo\bmiHeader\biWidth       = TemporaryBitmap\bmWidth
  TemporaryBitmapInfo\bmiHeader\biHeight      = -TemporaryBitmap\bmHeight
  TemporaryBitmapInfo\bmiHeader\biPlanes      = 1
  TemporaryBitmapInfo\bmiHeader\biBitCount    = 32
  TemporaryBitmapInfo\bmiHeader\biCompression = #BI_RGB
  
  GetDIBits_(TemporaryDC, ImageID(ImageNo), 0, TemporaryBitmap\bmHeight, Memory, TemporaryBitmapInfo, #DIB_RGB_COLORS)
  
  DeleteDC_(TemporaryDC)
  
EndProcedure


Procedure CopyMemoryToImage(Memory, ImageNo)
  
  Protected TemporaryDC.l, TemporaryBitmap.BITMAP, TemporaryBitmapInfo.BITMAPINFO
  
  TemporaryDC = CreateDC_("DISPLAY", #Null, #Null, #Null)
  
  GetObject_(ImageID(ImageNo), SizeOf(BITMAP), TemporaryBitmap.BITMAP)
  
  TemporaryBitmapInfo\bmiHeader\biSize        = SizeOf(BITMAPINFOHEADER)
  TemporaryBitmapInfo\bmiHeader\biWidth       = TemporaryBitmap\bmWidth
  TemporaryBitmapInfo\bmiHeader\biHeight      = -TemporaryBitmap\bmHeight
  TemporaryBitmapInfo\bmiHeader\biPlanes      = 1
  TemporaryBitmapInfo\bmiHeader\biBitCount    = 32
  TemporaryBitmapInfo\bmiHeader\biCompression = #BI_RGB
  
  SetDIBits_(TemporaryDC, ImageID(ImageNo), 0, TemporaryBitmap\bmHeight, Memory, TemporaryBitmapInfo, #DIB_RGB_COLORS)
  
  DeleteDC_(TemporaryDC)
  
EndProcedure

Procedure SwapRGB(Color)
  
  ProcedureReturn ((Color & $FF) << 16) | (Color & $FF00) | ((Color & $FF0000) >> 16)
  
EndProcedure

;- Macro

; Macro RGB(Red, Green, Blue)
;   
;   (((Blue << 8 + Green) << 8 ) + Red )
;   
; EndMacro
Procedure MyRGBA(Red,Green,Blue,Alpha)
  
  ProcedureReturn RGB(Blue,Green,Red) + Alpha << 24
EndProcedure
Macro FastRed(Color)
  
  Color & 255
  
EndMacro

Macro FastGreen(Color)
  
  (Color & 65535) >> 8
  
EndMacro

Macro FastBlue(Color)
  
  (Color & 16777215) >> 16
  
EndMacro

Macro FastPlot(x, y, Color)
  
  PokeL(*Memory + (x + ImageWidth * (y)) << 2, SwapRGB(Color))
  
EndMacro

Macro FastPoint(x, y)
  
  SwapRGB(PeekL(*Memory + (x + ImageWidth * (y)) << 2))
  
EndMacro
Procedure.l RGB32(R.l, G.l, B.l, A.l)
  RGBA.l = A << 24 + B << 16 + G << 8 + R
  ProcedureReturn RGBA
EndProcedure
Procedure.l R32(RGBA.l)
  R.l = RGBA & $FF
  ProcedureReturn R
EndProcedure
Procedure.l G32(RGBA.l)
  G.l = RGBA >> 8 & $FF
  ProcedureReturn G
EndProcedure
Procedure.l B32(RGBA.l)
  B.l = RGBA >> 16 & $FF
  ProcedureReturn B
EndProcedure
Procedure.l A32(RGBA.l)
  A.l = RGBA >> 24
  ProcedureReturn A
EndProcedure


Procedure.l RGB24(R.l, G.l, B.l)
  RGB.l = B << 16 + G << 8 + R
  ProcedureReturn RGB
EndProcedure
Procedure.l R24(RGB.l)
  R.l = RGB & $FF
  ProcedureReturn R
EndProcedure
Procedure.l G24(RGB.l)
  G.l = RGB >> 8 & $FF
  ProcedureReturn G
EndProcedure
Procedure.l B24(RGB.l)
  B.l = RGB >> 16
  ProcedureReturn B
EndProcedure


Procedure.l RGB16(R.l, G.l, B.l)
  R >> 3
  G >> 2
  B >> 3
  RGB.l = B << 11 + G << 5 + R
  ProcedureReturn RGB
EndProcedure
Procedure.l R16(RGB.l)
  R.l = (RGB & $1F) << 3
  ProcedureReturn R
EndProcedure
Procedure.l G16(RGB.l)
  G.l = (RGB >> 5 & $3F) << 2
  ProcedureReturn G
EndProcedure
Procedure.l B16(RGB.l)
  B.l = (RGB >> 11 & $1F) << 3
  ProcedureReturn B
EndProcedure


Procedure.l RGB15(R.l, G.l, B.l)
  R >> 3
  G >> 3
  B >> 3
  RGB.l = B << 10 + G << 5 + R
  ProcedureReturn RGB
EndProcedure
Procedure.l R15(RGB.l)
  R.l = (RGB & $1F) << 3
  ProcedureReturn R
EndProcedure
Procedure.l G15(RGB.l)
  G.l = (RGB >> 5 & $1F) << 3
  ProcedureReturn G
EndProcedure
Procedure.l B15(RGB.l)
  B.l = (RGB >> 10 & $1F) << 3
  ProcedureReturn B
EndProcedure
; Procedure BuildFont(name.s,height.l,bold.l,italic.b,symbol.l) ;Build Our Bitmap Font
;  ;ProcedureReturn 
;   
;   Global Dim gmf.f(256)
;   ;Protected font.l ;Windows Font ID
;   ;Protected oldfont.l ;Used For Good House Keeping
;   
;   ;    //Convert the ascii code into the position in the 16*14 array
;   charwidth=16
;   charheight=14
;   textureheight=256
;   texturewidth=256
;   
;   glBindTexture(#GL_TEXTURE_2D, font)
;   For character=32 To 255
;     line = (character-32)/16;
;     row  = (character-32)%16;
;     
;     ;   //convert the position of the fictitious array into the pixel position in the picture ( (0,0) is top left pixel)
;     topLeftX = row*charWidth:topLeftY=256-line*charHeight;
;     
;     
;     ;   If bold : bold=#FW_BOLD : Else : bold=#FW_NORMAL : EndIf ;font weight
;     ;   If symbol : symbol=#SYMBOL_CHARSET : Else : symbol=#ANSI_CHARSET : EndIf ;character set
;     ;
;     base=glGenLists(256) ;Storage For 96 Characters
;     ;      //Render the character With a texture quad
;     
;     
;     
;     glNewList(base+character,#GL_COMPILE)
;     ;glNewList(ImageList,#GL_COMPILE);
;     ;glBlendFunc(#GL_ONE,#GL_ONE)
;     ;glBindTexture_(#GL_TEXTURE_2D,texture) ;Select Our Texture
;     ;glBindTexture(#GL_TEXTURE_2D, texture)
;     ;glLoadIdentity() ;Reset The Current Matrix
;     glBegin(#GL_QUADS)
;     glTexCoord2f(0, 0): glVertex2f(0, 0) ;    Bottom Left Of The Texture And Quad
;     glTexCoord2f(0, imageheight/newimageheight): glVertex2f(0, imageheight);     Top Left Of The Texture And Quad
;     glTexCoord2f(imagewidth/newimagewidth,  imageheight/newimageheight): glVertex2f( imagewidth,  imageheight);     Top Right Of The Texture And Quad
;     glTexCoord2f(imagewidth/newimagewidth, 0): glVertex2f(imagewidth, 0);     Bottom Right Of The Texture And Quad
;     glEnd()
;     glEndList()
;     ;  glBegin(#GL_QUADS);
;     ;  glTexCoord2f( topLeftX       /textureWidth,  topLeftY        /textureHeight);
;     ;  glVertex2i(0,         charHeight);
;     ;
;     ;  glTexCoord2f( topLeftX       /textureWidth, (topLeftY-height)/textureHeight);
;     ;  glVertex2i(0,         0);
;     ;
;     ;  glTexCoord2f((topLeftX+width)/textureWidth, (topLeftY-height)/textureHeight);
;     ;  glVertex2i(charWidth, 0);
;     ;
;     ;  glTexCoord2f((topLeftX+width)/textureWidth,  topLeftY        /textureHeight);
;     ;  glVertex2i(charWidth, charHeight);
;     ;
;     ;  glEnd();
;     gltranslated(10,0,0)
;     glendlist()
;     
;   Next character
;   
; 
; ;   ;CreateFont_(Height, Width, Angle Of Escapement, Orientation Angle, Weight, Italic, Underline, Strikeout, Character Set, Output Precision, Clipping Precision, Output Quality, Family And Pitch, Name)
; ;   font=CreateFont_(-height,0,0,0,bold,italic,#False,#False,symbol,#OUT_TT_PRECIS,#CLIP_DEFAULT_PRECIS,#ANTIALIASED_QUALITY,#FF_DONTCARE | #DEFAULT_PITCH,name)
; ;   ;Debug font
; ;   oldfont=SelectObject_(hDC,font) ;Selects The Font We Want
; ;   ;Debug fontbase
; ;   wglUseFontOutlines_(hDC,32,96,base,0.1,0.2,1,gmf) ;Builds 96 Characters Starting At Character 32
; ;   SelectObject_(hDC,oldfont) ;reselect the old font again
; ;   DeleteObject_(font) ;Delete The Font
;   
; EndProcedure
; 
; Procedure KillFont() ;Delete The Font List
;   
;   glDeleteLists(base,256) ;Delete All 96 Characters
;   
; EndProcedure
; 
; ; Procedure glPrint(x,y,text.s) ;Custom GL "Print" Routine
; ;
; ;   If text="" ;If There's No Text
; ;     ProcedureReturn #False ;Do Nothing
; ;   EndIf
; ;   glLoadIdentity() ;Reset The Current Matrix
; ;   ;glRasterPos2f_(-0.45+0.05*Cos(cnt1),0.4*Sin(cnt2))
; ;      glTranslatef(x,y,0)
; ;   glPushAttrib_(#GL_LIST_BIT) ;Pushes The Display List Bits
; ;   glListBase_(fontbase-32) ;Sets The Base Character to 32
; ;   glCallLists_(Len(text),#GL_UNSIGNED_BYTE,text) ;Draws The Display List Text
; ;   glPopAttrib_() ;Pops The Display List Bits
; ;
; ; EndProcedure
; Procedure glprint(x,y,thisstring.s,set=0)
;  ; ProcedureReturn
;   ;glPushMatrix();
;   ;glPushAttrib(#GL_COLOR_BUFFER_BIT);
;   
;   glloadidentity()
;   ;glBlendFunc(#GL_SRC_ALPHA, #GL_ONE_MINUS_SRC_ALPHA);
; 
;   ;  glEnable(#GL_BLEND);
;   ;ProcedureReturn
;   glbindtexture(#GL_TEXTURE_2D,font)
;   ;gldisable(#gl_alpha_test)
;   ;glDisable(#GL_DEPTH_TEST)                     ; Disables Depth Testing
;   ; If status2d=#False
;   ;gldisable(#gl_texture_2d);NEEDED, SOME NON ATI DRIVERS DON'T DO THIS
; 	;glPushAttrib(#GL_LIST_BIT);				// Pushes the display list bits
; 	glListBase(base-32);					// Sets the base character to 0
; 	;Debug base
; 	;glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);	// Draws the display list text
; 					;	// Pops the display list bits
;   
;   ;glRasterPos2i(x,y)
;   gltranslated(x,y,0)
;   ;glListBase(base-32+(128*set)) ;Sets The Base Character to 32
;   ;   *m=AllocateMemory(Len(thisstring)+2);make memory(Len(thisstring)+1)                  ; Choose The Font Set (0 Or 1)
;   ;   PokeS(*m,thisstring); dump(m,thisstring)
;   glCallLists_(Len(thisstring),#GL_UNSIGNED_byte,thisstring) ;Draws The Display List Text
;   ;glcalllist(base) 
;   ;Debug spritelist
;   ;glPopAttrib();
; ;        glPopAttrib();
; ;      glMatrixMode( #GL_PROJECTION );
; ;      glPopMatrix();
; ;      glMatrixMode( #GL_MODELVIEW );
; ;      glPopMatrix();
; ;   FreeMemory( *m )
; 
; ;    Else
; ;gldisable(#gl_texture_2d);NEEDED, SOME NON ATI DRIVERS DON'T DO THIS
; ;      glbindtexture(#GL_TEXTURE_2D,1)
; ;      glLoadIdentity()                             ; Reset The Matrix
; ;     gltranslatef(x,y,0)
; ;     glListBase(fontbase-32) ;Sets The Base Character to 32
; ;     m=AllocateMemory(Len(thisstring)+2);make memory(Len(thisstring)+1)                  ; Choose The Font Set (0 Or 1)
; ;     PokeS(m,thisstring); dump(m,thisstring)
; ;     glCallLists(Len(thisstring),#GL_UNSIGNED_BYTE,m) ;Draws The Display List Text
; ;     FreeMemory( m )
; ;   ;EndIf
; ;glPopAttrib();
; ;glPopMatrix();
; EndProcedure
; Procedure BuildFont(name.s,height.l,bold.l,italic.b,symbol.l) ;Build Our Bitmap Font
;
;   Protected font.l ;Windows Font ID
;   Protected oldfont.l ;Used For Good House Keeping
;
;   If bold : bold=#FW_BOLD : Else : bold=#FW_NORMAL : EndIf ;font weight
;   If symbol : symbol=#SYMBOL_CHARSET : Else : symbol=#ANSI_CHARSET : EndIf ;character set
;
;   base=glGenLists_(96) ;Storage For 96 Characters
;
;   ;CreateFont_(Height, Width, Angle Of Escapement, Orientation Angle, Weight, Italic, Underline, Strikeout, Character Set, Output Precision, Clipping Precision, Output Quality, Family And Pitch, Name)
;   font=CreateFont_(-height,0,0,0,bold,italic,#False,#False,symbol,#OUT_TT_PRECIS,#CLIP_DEFAULT_PRECIS,#ANTIALIASED_QUALITY,#FF_DONTCARE | #DEFAULT_PITCH,name)
;   Debug base
;   oldfont=SelectObject_(hDC,font) ;Selects The Font We Want
;   wglUseFontBitmaps_(hDC,32,96,base) ;Builds 96 Characters Starting At Character 32
;   SelectObject_(hDC,oldfont) ;reselect the old font again
;   DeleteObject_(font) ;Delete The Font
;
; EndProcedure
; Procedure BuildFont() ;Build Our Font Display List
;   ;**********************************************************************
;   ;Texture Coord system is DirectX style, not OpenGL reversed
;   ;**********************************************************************
;   Protected cx.f ;Holds Our X Character Coord
;   Protected cy.f ;Holds Our Y Character Coord
;   Protected modx.l ;modulus for x coord
;   fontwidth=32
;   fontheight=32
;   base=glGenLists_(256) ;Creating 256 Display Lists
;   
;   glBindTexture_(#GL_TEXTURE_2D,font) ;Select Our Font Texture
;   
;   For loop=0 To 256-1 ;Loop Through All 256 Lists
;     modx=loop % 16 ;Note: can't use % with floats
;     cx=modx/16 ;X Position Of Current Character
;     cy=Int(loop/16)/16 ;Y Position Of Current Character
;     
;     glNewList_(base+loop,#GL_COMPILE) ;Start Building A List
;     glBegin_(#GL_QUADS) ;Use A Quad For Each Character
;     glTexCoord2f_(cx,1-cy) ;Texture Coord (Bottom Left)
;     glVertex2i_(0,0) ;Vertex Coord (Bottom Left)
;     glTexCoord2f_(cx+0.0625,1-cy) ;Texture Coord (Bottom Right)
;     glVertex2i_(fontwidth,0) ;Vertex Coord (Bottom Right)
;     glTexCoord2f_(cx+0.0625,1-cy-0.0625) ;Texture Coord (Top Right)
;     glVertex2i_(fontwidth,fontheight) ;Vertex Coord (Top Right)
;     glTexCoord2f_(cx,1-cy-0.0625) ;Texture Coord (Top Left)
;     glVertex2i_(0,fontheight) ;Vertex Coord (Top Left)
;     glEnd_() ;Done Building Our Quad (Character)
;     glTranslated(fontwidth-(fontwidth/2)+4*(fontwidth/32),0,0) ;Move To The Right Of The Character
;     glEndList_() ;Done Building The Display List
;   Next ;Loop Until All 256 Are Built
;   
; EndProcedure
; Procedure KillFont() ;Delete The Font List
;   
;   glDeleteLists_(base,256) ;Delete All 96 Characters
;   
; EndProcedure
; 
; ; Procedure glPrint(x,y,text.s) ;Custom GL "Print" Routine
; ;
; ;   If text="" ;If There's No Text
; ;     ProcedureReturn #False ;Do Nothing
; ;   EndIf
; ;   glloadidentity()
; ;   glPushAttrib_(#GL_LIST_BIT) ;Pushes The Display List Bits
; ;   glListBase_(base-32) ;Sets The Base Character to 32
; ;  glrasterpos2i(x,y)
; ;   glCallLists_(Len(text),#GL_UNSIGNED_BYTE,text) ;Draws The Display List Text
; ;   glPopAttrib_() ;Pops The Display List Bits
; ;
; ; EndProcedure;
; Procedure glPrint(x.l, y.l, string.s, set = 0) ;Where The Printing Happens
;   
;   If set : set = 1 : EndIf ;Is set True? If So, Make set Equal One
;   glDisable(#gl_cull_Face)
;   glBindTexture_(#GL_TEXTURE_2D, font) ;Select Our Font Texture
;   
;   ;   glDisable_(#GL_DEPTH_TEST) ;Disables Depth Testing
;   ;   glMatrixMode_(#GL_PROJECTION) ;Select The Projection Matrix
;   ;   glPushMatrix_() ;Store The Projection Matrix
;   ;   glLoadIdentity_() ;Reset The Projection Matrix
;   ;   glOrtho(0,800,600,0,-1,1) ;Set Up An Ortho Screen
;   ;   glMatrixMode_(#GL_MODELVIEW) ;Select The Modelview Matrix
;   ;   glPushMatrix_() ;Store The Modelview Matrix
;   glLoadIdentity_() ;Reset The Modelview Matrix
;   glTranslated(x, y, 0) ;Position The Text (0,0 - Bottom Left)
;   glListBase_(base) ;Choose The Font Set (0 or 1)
;   glCallLists_(Len(string), #GL_BYTE, string) ;Write The Text To The Screen
;   ;   glMatrixMode_(#GL_PROJECTION) ;Select The Projection Matrix
;   ;   glPopMatrix_() ;Restore The Old Projection Matrix
;   ;   glMatrixMode_(#GL_MODELVIEW) ;Select The Modelview Matrix
;   ;   glPopMatrix_() ;Restore The Old Projection Matrix
;   ;   glEnable_(#GL_DEPTH_TEST) ;Enables Depth Testing
;   ; ;
;   glEnable(#gl_cull_Face)
; EndProcedure
; Procedure BuildFont()
;   
;   ; Build Our Font Display List
;   Protected cx.d                              ; Holds Our X Character Coord
;   Protected cy.d
;   ; Holds Our Y Character Coord
;   ;Debug font
;   ; Debug texture
;   
;   base=glGenLists_(256)                        ; Creating 256 Display Lists
;   glBindTexture(#GL_TEXTURE_2D, font); Select Our Font Texture
;   ;Debug fontbase
;   tempx.d
;   tempy.d
;   For loops=0 To 255
;     
;     ; Loop Through All 256 Lists
;     tempx=mod_f(loops,16.0)
;     tempy=loops / 16
;     cx=tempx/16.0                     ; X Position Of Current Character
;     cy=tempy/16.0                     ; Y Position Of Current Character
;     ;     Debug cx
;     ;     Debug cy
;     glNewList(base+loops,#GL_COMPILE)        ; Start Building A List
;     ;Debug base+loops
;     glBegin(#GL_QUADS)                     ; Use A Quad For Each Character
;     glTexCoord2f(cx,1-cy-0.0625)         ; Texture Coord (Bottom Left)
;     glVertex2i(0,0)                     ; Vertex Coord (Bottom Left)
;     glTexCoord2f(cx+0.0625,1-cy-0.0625)   ; Texture Coord (Bottom Right)
;     glVertex2i(16,0)                  ; Vertex Coord (Bottom Right)
;     glTexCoord2f(cx+0.0625,1-cy)         ; Texture Coord (Top Right)
;     glVertex2i(16,16)                  ; Vertex Coord (Top Right)
;     glTexCoord2f(cx,1-cy)               ; Texture Coord (Top Left)
;     glVertex2i(0,16)                  ; Vertex Coord (Top Left)
;     glEnd()                              ; Done Building Our Quad (Character)
;     glTranslated(10,0,0)                  ; Move To The Right Of The Character
;     glEndList()                              ; Done Building The Display List
;   Next loops                                 ; Loop Until All 256 Are Built
;   
; EndProcedure

; Debug A32(RGB32(1, 2, 3, 4))
; 
; Debug R24(RGB24(5, 6, 7))
; 
; Debug G16(RGB16(88, 99, 110))
; 
; Debug B15(RGB15(63, 127, 255))
; IDE Options = PureBasic 4.51 (Windows - x86)
; CursorPosition = 20
; Folding = -----
; UseMainFile = OpenGlEngineTest2.pb
; DisableDebugger